package com.sgl.gk.controller;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sg.comm.common.Ret;
import com.sg.comm.opcuav2.NodeDTOV2;
import com.sg.comm.opcuav2.OpcUaReadReqV2;
import com.sg.comm.opcuav2.OpcUaWriteReqV2;
import com.sg.comm.opcuav2.batch.BatchReadDTO;
import com.sg.comm.serialport.SerialPortBatchDTO;
import com.sg.comm.serialport.SerialPortBatchReadReq;
import com.sg.comm.serialport.SerialPortDTO;
import com.sg.comm.service.OpcUaServiceV2;
import com.sg.comm.service.SerialPortService;
import com.sgl.common.core.domain.AjaxResult;
import com.sgl.common.utils.StringUtils;
import com.sgl.gk.controller.vo.ConfigValueAndConfigConnectVo;
import com.sgl.gk.controller.vo.GkProductionLineVo;
import com.sgl.gk.controller.vo.GkStationConfigurationVo;
import com.sgl.gk.controller.vo.GkStationVo;
import com.sgl.gk.domain.*;
import com.sgl.gk.domain.plc.OpcUa;
import com.sgl.gk.domain.plc.OpcUaList;
import com.sgl.gk.mapper.*;
import com.sgl.gk.scheduled.ScheduledTask;
import com.sgl.gk.scheduled.vo.ServiceData;
import com.sgl.gk.scheduled.vo.SocketDataVo;
import com.sgl.gk.service.GkStationService;
import com.sgl.gk.tools.OpcUATool;
import com.sgl.gk.tools.ReadOpcUaNodeInfoTool;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author:xec
 * @date:2022/11/10 17:17
 * 监听保存读取controller：已不使用！
 **/
@Transactional
@RestController
@Slf4j
public class TaskScheduledController {

    @Autowired
    GkStationEventMapper gkStationEventMapper;

    @Autowired
    GkStationConfigurationMapper gkStationConfigurationMapper;

    @Autowired
    GkStationConfigurationConnectMapper gkStationConfigurationConnectMapper;

    @Autowired
    GkStationConfigurationValuesMapper gkStationConfigurationValuesMapper;

    @Autowired
    GkStationMapper gkStationMapper;

    @Autowired
    GkProductMapper gkProductMapper;

    @Autowired
    GkProductionLineMapper gkProductionLineMapper;

    @Autowired
    GkStatisticsMapper gkStatisticsMapper;

    @Autowired
    GkReservedInfoMapper gkReservedInfoMapper;

    @Autowired
    GkEquipmentMapper gkEquipmentMapper;

//    @DubboReference(version = "1.0.0", url = "dubbo://127.0.0.1:20880", check = false)
    private OpcUaServiceV2 opcUaServiceV2;

//    @DubboReference(version = "1.0.0", url = "dubbo://127.0.0.1:20880", check = false)
    private SerialPortService serialPortService;

    @Autowired
    GkSignalCommunicationMapper gkSignalCommunicationMapper;

    @Autowired
    GkShowStationInfoMapper gkShowStationInfoMapper;

    @Autowired
    GkSettingMapper gkSettingMapper;

    @Autowired
    GkStationService gkStationService;


    @PostMapping("/bb")
    public AjaxResult bb() {
//        List<SerialPortBatchDTO> aa = new ArrayList<>();
//        aa.add(e);
//        aa.addAll(newDate);
//        newDate = aa;
//        return AjaxResult.success(newDate);
        try {
            File file = new File("D:/sg/deleteConfigLog.txt");
            if (!file.exists()) {
                // 如果文件不存在，则创建文件及其所在的目录
                file.getParentFile().mkdirs();
                file.createNewFile();
            }
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonArrayString = "objectMapper.writeValueAsString()";

            String updatedJsonArrayStringWithPadding = "\n" + jsonArrayString + "\n";

            try (BufferedWriter writer = Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8, StandardOpenOption.APPEND)) {
                writer.write(updatedJsonArrayStringWithPadding);
            } catch (IOException e) {
                // 处理写入文件出错的异常
                e.printStackTrace();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return AjaxResult.success();
    }

    @GetMapping("/onlyRead")
    @ResponseBody
    public AjaxResult onlyRead(String uuid) {
        OpcUaReadReqV2 opcUaReadReqV2 = new OpcUaReadReqV2();
        opcUaReadReqV2.setUid(uuid);
        BatchReadDTO data = null;
        try {
            data = opcUaServiceV2.readData(opcUaReadReqV2).getData();
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
        log.info("是否连接：{}", data);
        for (NodeDTOV2 datum : data.getDtoList()) {
            log.info("读取数据：{}", datum.toString());
        }
        return AjaxResult.success(data);
    }

    @GetMapping("/read")
    @ResponseBody
    public String read() {
        OpcUaReadReqV2 opcUaReadReqV2 = new OpcUaReadReqV2();
        opcUaReadReqV2.setUid("PLC-2019-JC-XN");


        GkStation gkStation = new GkStation();
        gkStation.setId(29l);
        List<GkStationVo> list = gkStationService.list(gkStation);

        GkStationConfigurationConnect gkStationConfigurationConnect = new GkStationConfigurationConnect();
        for (GkStationVo gkStationVo : list) {
            gkStationConfigurationConnect.setStationId(gkStationVo.getId());
            gkStationConfigurationConnect.setProductId(gkStationVo.getProductId());
            gkStationConfigurationConnect.setProductName(gkStationVo.getProductName());
            gkStationConfigurationConnect.setProductLineId(gkStationVo.getProductionLineId());
            gkStationConfigurationConnect.setProductLineName(gkStationVo.getProductionLineName());
            gkStationConfigurationConnect.setCreateAt(new Date());
            gkStationConfigurationConnect.setLastModifyAt(new Date());
        }
        int row = gkStationConfigurationConnectMapper.add(gkStationConfigurationConnect);
        Long connectId = null;
        if (row > 0) {
            connectId = gkStationConfigurationConnectMapper.getMaxId();
            List<GkStationEvent> gkStationEventList = gkStationEventMapper.selectInfosByStationId(29l);
            List<Long> stationIds = new ArrayList<>();
            for (GkStationEvent gkStationEvent : gkStationEventList) {
                for (String s : gkStationEvent.getConditionStationId().split(",")) {
                    stationIds.add(Long.parseLong(s));
                }
            }
            if (stationIds.size() > 0) {
                List<GkStationConfigurationValues> valuesList = new ArrayList<>();
                for (GkStationConfigurationValues stationConfigurationValues : valuesList) {
                    System.out.println(stationConfigurationValues.toString());
                }
                row = gkStationConfigurationValuesMapper.saveList(valuesList);

                if (row > 0) {
                    return "查询数据成功";
                }
            }
        }

        return null;
    }


    @Value("${communication.mode}")
    public String communication;

    BufferedReader reader = null;

    BufferedWriter writer = null;

    Map<Long, Boolean> saveConfigureMap = new HashMap<>();

    Map<Long, Boolean> scanningMap = new HashMap<>();

    public Map<String, List<NodeDTOV2>> map = new HashMap<>();

    @PostConstruct
    public void doTask1() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 判断当前连接模式
                if (communication.equals("socket")) {
                    try {
                        Socket socket = new Socket("127.0.0.1", 8888);
                        reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
                // 循环监听事件是否到达条件
                while (true) {
                    try {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                        List<GkStationEvent> list = gkStationEventMapper.list(null);
                        if (CollUtil.isNotEmpty(list)) {
                            // 根据需要读取的条件变量分组
                            Map<Long, List<GkStationEvent>> conditionInfoMap = list.parallelStream().collect(Collectors.groupingBy(GkStationEvent::getConditionConfigurationId));

                            List<GkSignalCommunication> gkSignalCommunications = gkSignalCommunicationMapper.list(null);

                            int flag = 0;
                            // 获取所有plc的值，放入map，uuid为key
                            for (GkSignalCommunication gkSignalCommunication : gkSignalCommunications) {
                                OpcUaReadReqV2 opcUaReadReqV2 = new OpcUaReadReqV2();
                                opcUaReadReqV2.setUid(gkSignalCommunication.getCommunicationProtocol());
                                // 判断连接模式，不同模式获取值方式不同
                                if (communication.equals("socket")) {
                                    try {
                                        writer.write(gkSignalCommunication.getCommunicationProtocol() + "\n");
                                        writer.flush();
                                        BatchReadDTO batchReadDTO = readlineToObj();
                                        if (batchReadDTO == null) {
                                            gkSignalCommunication.setType(0);
                                            flag = 1;
                                        } else {
                                            map.put(batchReadDTO.getUid(), batchReadDTO.getDtoList());
                                            gkSignalCommunication.setType(1);
                                            flag = 1;
                                        }
                                    } catch (IOException e) {
                                        throw new RuntimeException(e);
                                    }
                                } else {
                                    BatchReadDTO data1 = null;
                                    try {
                                        data1 = opcUaServiceV2.readData(opcUaReadReqV2).getData();
                                    } catch (Exception e) {
                                        log.error("opcUaServiceV2.readData(opcUaReadReqV2).getData()出错");
                                    }
                                    if (data1 != null) {
//                                    log.info("UUid:{},是否连接：{}", gkSignalCommunication.getCommunicationProtocol(), data1.getIsConn());
                                    }
                                    if (data1 != null && data1.getIsConn()) {
                                        map.put(gkSignalCommunication.getCommunicationProtocol(), data1.getDtoList());
                                        if (gkSignalCommunication.getType() != 1) {
                                            gkSignalCommunication.setType(1);
                                            flag = 1;
                                        }
                                    } else {
                                        // 判断当前通信状态，若是断开连接则修改状态
                                        if (gkSignalCommunication.getType() != 0) {
                                            gkSignalCommunication.setType(0);
                                            flag = 1;
                                        }
                                    }
                                }
                            }
                            if (flag == 1) {
                                gkSignalCommunicationMapper.editList(gkSignalCommunications);
                            }
                            // 条件变量工位，需要修改工位信息都是一样的
                            List<Long> stationId = list.stream().map(GkStationEvent::getStationId).collect(Collectors.toList());
                            List<GkStation> gkStationAllList = gkStationMapper.selectInfosByIds(stationId);
                            // 条件变量信息,需要改变变量信息都是在同一默认工位下
                            List<GkStationConfiguration> gkStationConfigurationList = gkStationConfigurationMapper.selectInfoByStations(stationId.toArray(new Long[0]));

                            // 找出所有产线信息，保存变量值时需要使用
                            List<GkProductionLineVo> gkProductionLineVos = gkProductionLineMapper.list(null);

                            for (Long aLong : conditionInfoMap.keySet()) {
                                List<GkStationEvent> gkStationEventList = conditionInfoMap.get(aLong);
                                // 判断条件变量值与plc变量值是否匹配
                                long start = new Date().getTime();
                                judge(gkStationEventList, gkStationAllList, gkSignalCommunications, gkStationConfigurationList, gkProductionLineVos);

                            }
                        }
                    }catch (Exception e){
                        log.error(e.getMessage());
                    }
                }
            }
        }).start();
    }

    public BatchReadDTO readlineToObj() {
        try {
            BatchReadDTO batchReadDTO = new BatchReadDTO();
            String s = reader.readLine();
            if (!s.equals("NO")) {
                List<SocketDataVo> socketDataVos = null;
                try {
                    socketDataVos = JSON.parseArray(s, SocketDataVo.class);
                } catch (Exception e) {
                    System.out.println(s);
                    log.error(e.getMessage());
                }
                if (CollUtil.isNotEmpty(socketDataVos)) {
                    for (SocketDataVo object : socketDataVos) {
                        SocketDataVo socketDataVo = object;
                        List<ServiceData> nodeList = socketDataVo.getNodeList();
                        List<NodeDTOV2> nodeDTOV2List = new ArrayList<>();
                        for (ServiceData serviceData : nodeList) {
                            NodeDTOV2 nodeDTOV2 = new NodeDTOV2();
                            nodeDTOV2.setNodeValue(serviceData.getNodeValue());
                            nodeDTOV2.setNodeId(serviceData.getNodeId());
                            nodeDTOV2.setNodeType(serviceData.getNodeType());
                            nodeDTOV2.setNodeName(serviceData.getNodeName());
                            nodeDTOV2.setDisplayName(serviceData.getDisplayName());
                            nodeDTOV2List.add(nodeDTOV2);
                        }
                        batchReadDTO.setUid(socketDataVo.getUid());
                        batchReadDTO.setDtoList(nodeDTOV2List);
                    }
                    return batchReadDTO;
                }else {
                    return null;
                }
            } else {
                return null;
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    Long nowTime = 0l;


    List<SerialPortBatchDTO> newDate = new ArrayList<>();

    /**
     * 扫码匹配
     *
     * @param conditionId            需要扫码的工位id
     * @param gkSignalCommunications 所有的通讯id，修改时需要使用
     * @param gkProductionLineVos    所有产线的信息
     * @param gkStationEvent         需要扫码的工位信息
     */
    private void Scancodematching(Long conditionId, List<GkSignalCommunication> gkSignalCommunications,
                                  List<GkProductionLineVo> gkProductionLineVos, GkStationEvent gkStationEvent) {
        GkEquipment gkEquipment = new GkEquipment();
        gkEquipment.setStationId(conditionId);
        List<GkEquipment> gkEquipmentList = gkEquipmentMapper.list(gkEquipment);
        log.info("gkEquipmentList:{}", JSONUtil.toJsonStr(gkEquipment));
        nowTime = new Date().getTime();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    log.info("需要扫码,工位id为：{}", conditionId);
                    SerialPortBatchReadReq serialPortBatchReadReq = new SerialPortBatchReadReq();
                    Ret<List<SerialPortBatchDTO>> listRet = null;
                    List<SerialPortBatchDTO> data = new ArrayList<>();
                    try {
                        listRet = serialPortService.batchReadData(serialPortBatchReadReq);
                        data = listRet.getData();
                    } catch (Exception e) {
                        log.error("定时任务扫码枪连接失败");
                        if (communication.equals("socket")) {
                            if (newDate.size() > 0) {
                                data = newDate;
                            }
                        }
                    }
                    log.info("获取到扫码值：{}", JSONUtil.toJsonStr(data));
                    for (GkEquipment equipment : gkEquipmentList) {
                        for (SerialPortBatchDTO datum : data) {
                            // 找到扫码枪
                            if (equipment.getSerialPortName().equals(datum.getUid())) {
                                if (datum.getIsConn()) {
                                    List<SerialPortDTO> dtoList = datum.getDtoList();
                                    if (!CollUtil.isNotEmpty(dtoList)) {
                                        continue;
                                    }
                                    SerialPortDTO serialPortDTO = dtoList.get(0);
                                    if (serialPortDTO.getLastModifyAt() >= nowTime) {
                                        String dataStr = serialPortDTO.getDataStr();
                                        log.info("扫码成功值为：{}", dataStr);
                                        // 得到值后进行匹配改写
                                        long startTime = new Date().getTime();
                                        Boolean aBoolean = editBarCode(dataStr, conditionId, gkSignalCommunications, gkProductionLineVos, gkStationEvent);
                                        if (aBoolean) {
                                            long endTime = new Date().getTime();
                                            log.info("匹配成功,耗时：{}", endTime - startTime);
                                            ScheduledTask.isMatching = true;
                                            scanningMap.put(conditionId, false);
                                        } else {
                                            long endTIme = new Date().getTime();
                                            ScheduledTask.isMatching = false;
                                            ScheduledTask.scanningBarCode = dataStr;
                                            log.info("匹配失败,耗时：{}", endTIme - startTime);
                                        }
                                        nowTime = new Date().getTime();
                                        if (communication.equals("socket")) {
                                            newDate.clear();
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    if (!scanningMap.get(conditionId)) {
                        break;
                    }
                }
            }
        }).start();
    }

    /**
     * 扫码匹配成功，进行参数下发
     *
     * @param dataStr                扫码参数
     * @param conditionId            扫码下发工位
     * @param gkSignalCommunications 所有通讯信息
     * @param gkProductionLineVos    所有产线信息
     * @param gkStationEvent         当前事件信息
     * @return 是否匹配下发成功
     */
    private Boolean editBarCode(String dataStr, Long conditionId, List<GkSignalCommunication> gkSignalCommunications, List<GkProductionLineVo> gkProductionLineVos, GkStationEvent gkStationEvent) {
        List<GkStationConfiguration> gkStationConfigurationList1 = gkStationConfigurationMapper.selectInfoByStations(new Long[]{conditionId, gkStationEvent.getStationId()});
        List<GkStationConfiguration> gkStationConfigurationListType1 = gkStationConfigurationList1.stream().filter(gkStationConfiguration -> gkStationConfiguration.getType() == 1).collect(Collectors.toList());
        List<GkStationConfiguration> gkStationConfigurationListType2 = gkStationConfigurationList1.stream().filter(gkStationConfiguration -> gkStationConfiguration.getType() == 2).collect(Collectors.toList());
        GkStation gkStation = gkStationMapper.selectInfoById(conditionId);
        // 匹配成功需要修改的条件变量和反馈变量信息集合
        List<GkStationConfiguration> gkStationConfigurationList = gkStationConfigurationList1.stream().filter(gkStationConfiguration -> gkStationConfiguration.getType() == 3 || gkStationConfiguration.getType() == 4).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(gkStationConfigurationListType1)) {
            OpcUaWriteReqV2 opcUaWriteReqV2 = new OpcUaWriteReqV2();
            List<NodeDTOV2> nodeDTOV2List = null;
            for (GkSignalCommunication gkSignalCommunication : gkSignalCommunications) {
                if (gkStation.getSignalCommunicationId().longValue() == gkSignalCommunication.getId().longValue()) {
                    nodeDTOV2List = map.get(gkSignalCommunication.getCommunicationProtocol());
                    opcUaWriteReqV2.setUid(gkSignalCommunication.getCommunicationProtocol());
                }
            }
            for (GkStationConfiguration gkStationConfiguration : gkStationConfigurationListType1) {
                String prefix = "barcode";
                String suffix = "en";
                String suffix2 = "format";
                for (int i = 0; i < 6; i++) {
                    String name = prefix + (i) + suffix;
                    // todo 新增
                    if (i == 0) {
                        name = prefix + suffix;
                    }
                    // 判断设置参数内是否有barCodeXXen参数
                    if (gkStationConfiguration.getVariableName().trim().toLowerCase().equals(name)) {
                        // 匹配最新值
                        String variableName = "DB_RECIPE." + (StringUtils.isEmpty(gkStation.getCode()) ? "" : (gkStation.getCode() + ".")) + gkStationConfiguration.getVariableName();
                        for (NodeDTOV2 nodeDTOV2 : nodeDTOV2List) {
                            if (variableName.equals(nodeDTOV2.getDisplayName())) {
                                String nodeValue = OpcUATool.getValue(nodeDTOV2);
                                // 把最新值赋给defaultValue
                                gkStationConfiguration.setDefaultValue(nodeValue);
                            }
                        }
                        // barCodeXXen最新值不为空并且默认值为true时进行barCodeXXformat匹配
                        if (!StringUtils.isEmpty(gkStationConfiguration.getDefaultValue()) && gkStationConfiguration.getDefaultValue().equals("true")) {
                            String endName = prefix + (i) + suffix2;
                            if (i == 0) {
                                endName = prefix + suffix2;
                            }
                            for (GkStationConfiguration stationConfiguration : gkStationConfigurationListType1) {
                                // 判断设置参数内是否有barCodeXXformat参数
                                if (stationConfiguration.getVariableName().toLowerCase().equals(endName)) {
                                    variableName = "DB_RECIPE." + (StringUtils.isEmpty(gkStation.getCode()) ? "" : (gkStation.getCode() + ".")) + stationConfiguration.getVariableName();
                                    for (NodeDTOV2 nodeDTOV2 : nodeDTOV2List) {
                                        if (variableName.equals(nodeDTOV2.getDisplayName())) {
                                            String nodeValue = OpcUATool.getValue(nodeDTOV2);
                                            stationConfiguration.setDefaultValue(nodeValue);
                                        }
                                    }
                                    // 判断扫码值是否以最新的barCodeXXformat值为前缀
                                    if (!StringUtils.isEmpty(stationConfiguration.getDefaultValue()) && StringUtils.startsWith(dataStr, stationConfiguration.getDefaultValue())) {
                                        ArrayList<NodeDTOV2> writeNodeList = new ArrayList<>();
                                        // 判断成功，把扫码值与事件需要修改的值一起写入plc
                                        for (GkStationConfiguration configuration : gkStationConfigurationListType2) {
                                            // 判断保存变量内是否有barCodeXX变量
                                            String anObject = prefix + (i);
                                            if (i == 0) {
                                                anObject = prefix;
                                            }
                                            if (configuration.getVariableName().trim().toLowerCase().equals(anObject)) {
                                                NodeDTOV2 nodeDTOV2 = new NodeDTOV2();
                                                nodeDTOV2.setNodeValue(dataStr);
                                                nodeDTOV2.setNodeType(configuration.getDataType().toUpperCase());
                                                String nodeName = "";
                                                for (GkProductionLineVo gkProductionLineVo : gkProductionLineVos) {
                                                    if (gkStation.getProductionLineId().longValue() == gkProductionLineVo.getId().longValue()) {
                                                        nodeName = gkProductionLineVo.getCode() + "." + (StringUtils.isEmpty(gkStation.getCode()) ? "" : (gkStation.getCode() + ".")) + configuration.getVariableName();
                                                    }
                                                }
                                                nodeDTOV2.setNodeName(nodeName);
                                                writeNodeList.add(nodeDTOV2);
                                            }
                                        }
                                        // 需要修改的条件变量和反馈变量
                                        for (GkStationConfiguration configuration : gkStationConfigurationList) {
                                            // 条件变量反馈
                                            if (gkStationEvent.getConditionConfigurationId().longValue() == configuration.getId().longValue()) {
                                                NodeDTOV2 nodeDTOV2 = new NodeDTOV2();
                                                nodeDTOV2.setNodeValue(0);
                                                nodeDTOV2.setNodeName("data_pc_plc.plc_request." + configuration.getVariableName());
                                                nodeDTOV2.setNodeType(configuration.getDataType().toUpperCase());
                                                writeNodeList.add(nodeDTOV2);
                                            }
                                            if (gkStationEvent.getConfigurationId().longValue() == configuration.getId().longValue()) {
                                                NodeDTOV2 nodeDTOV2 = new NodeDTOV2();
                                                nodeDTOV2.setNodeName("data_pc_plc.pc_reply." + configuration.getVariableName());
                                                nodeDTOV2.setNodeType(configuration.getDataType().toUpperCase());
                                                Object configurationValue = getConfigurationValue(configuration);
                                                nodeDTOV2.setNodeValue(configurationValue);
                                                writeNodeList.add(nodeDTOV2);
                                            }
                                        }
                                        opcUaWriteReqV2.setWriteNodeList(writeNodeList);
                                        log.info("发送数据:{}", JSONUtil.toJsonStr(writeNodeList));
                                        if (communication.equals("socket")) {
                                            long time = new Date().getTime();
                                            writerToObj(opcUaWriteReqV2);
                                            long end = new Date().getTime();
                                            log.info("发送时间:{}", end - time);
                                        } else if (communication.equals("plc")) {
                                            long time = new Date().getTime();
                                            Ret<List<NodeDTOV2>> listRet = opcUaServiceV2.writeData(opcUaWriteReqV2);
                                            if (listRet != null) {
                                                List<NodeDTOV2> data = listRet.getData();
                                                if (CollUtil.isNotEmpty(data)) {
                                                    for (NodeDTOV2 datum : data) {
                                                        if (datum.getStatusCode().longValue() != 0) {
                                                            return false;
                                                        }
                                                    }
                                                } else {
                                                    return false;
                                                }
                                            } else {
                                                return false;
                                            }
                                            long end = new Date().getTime();
                                            log.info("发送匹配成功条码时间耗时:{}", end - time);
                                        }
                                        return true;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        ScheduledTask.barCodeStationName = gkStation.getName();
        return false;
    }

    /**
     * 保存读取的工位变量信息
     *
     * @param gkProductionLineVos      所有产线信息
     * @param gkStationEvent           保存的事件信息
     * @param saveOrScanningStationIds 需要保存的工位id
     * @param gkSignalCommunications   所有通讯信息
     */
    private void saveConfigurationValue(List<GkProductionLineVo> gkProductionLineVos, GkStationEvent gkStationEvent,
                                        List<Long> saveOrScanningStationIds, List<GkSignalCommunication> gkSignalCommunications) {
        List<GkStation> saveStationInfos = gkStationMapper.selectInfosByIds(saveOrScanningStationIds);
        List<GkStationConfigurationVo> saveConfigurationInfos = gkStationConfigurationMapper.selectInfoByType2StationIds(saveOrScanningStationIds);
        Map<Long, List<GkStationConfigurationVo>> saveConfigurationInfoMap = saveConfigurationInfos.parallelStream().collect(Collectors.groupingBy(GkStationConfigurationVo::getStationId));
        GkStation gkStation = gkStationMapper.selectInfoById(gkStationEvent.getStationId());

//        List<ConfigValueAndConfigConnectVo> configValueAndConfigConnectVos = gkStationConfigurationValuesMapper.selectAllInfoAndConfigInfo();
//        configValueAndConfigConnectVos = configValueAndConfigConnectVos.stream().filter(configvalue -> !StringUtils.isEmpty(configvalue.getValue())).collect(Collectors.toList());
        Date date = new Date();
        // 获取最新的工位保存数据的连接表id
        Long maxConnectId = new Long(0l);
        for (GkProductionLineVo gkProductionLineVo : gkProductionLineVos) {
            if (gkStation.getProductionLineId().longValue() == gkProductionLineVo.getId().longValue()) {
                // 只添加一次连接表id
                GkStationConfigurationConnect gkStationConfigurationConnect = new GkStationConfigurationConnect();
                gkStationConfigurationConnect.setStationId(gkStation.getId());
                gkStationConfigurationConnect.setProductLineId(gkProductionLineVo.getId());
                gkStationConfigurationConnect.setProductLineName(gkProductionLineVo.getName());
                gkStationConfigurationConnect.setResult(1);
                gkStationConfigurationConnect.setCreateAt(date);
                gkStationConfigurationConnect.setLastModifyAt(date);
                gkStationConfigurationConnectMapper.add(gkStationConfigurationConnect);
                maxConnectId = gkStationConfigurationConnect.getId();
//                maxConnectId = 2737l;
            }
        }
        // 合格与不合格标识  0 为没有不合格  1  为有不合格
        int flag = 0;
        // 总成码
        String assemblyCode = new String();
        // 追溯码
        String traceabilityCode = new String();
        String productName = new String();
        List<GkStationConfigurationValues> gkStationConfigurationValuesList = new ArrayList<>();
        int size = saveStationInfos.size();
        int index = 0;
        Long connectId = 0l;
        List<String> values = new ArrayList<>();
        List<Long> connectIds = new ArrayList<>();
        for (GkStation saveStationInfo : saveStationInfos) {
            if (saveStationInfo.getSignalCommunicationId() != null) {
                index += 1;
                for (GkSignalCommunication gkSignalCommunication : gkSignalCommunications) {
                    if (saveStationInfo.getSignalCommunicationId().longValue() == gkSignalCommunication.getId().longValue()) {

                        List<NodeDTOV2> nodeDTOV2List = map.get(gkSignalCommunication.getCommunicationProtocol());
                        if (nodeDTOV2List == null) {
                            log.error("当前{}返回值为空", saveStationInfo.getName());
                            continue;
                        }

                        List<GkStationConfigurationVo> saveConfigurationInfoList = saveConfigurationInfoMap.get(saveStationInfo.getId());
                        for (NodeDTOV2 nodeDTOV2 : nodeDTOV2List) {
                            for (GkStationConfigurationVo gkStationConfigurationVo : saveConfigurationInfoList) {
                                // 拼接nodeName
                                String nodeName = "";
                                for (GkProductionLineVo gkProductionLineVo : gkProductionLineVos) {
                                    if (gkProductionLineVo.getId().longValue() == saveStationInfo.getProductionLineId().longValue()) {
                                        // 配置数据源。因为总成装配线的OP110等数据在Data里面拿取数据
                                        // todo 事件数据源的读取
                                        if (StringUtils.isNotEmpty(gkStationEvent.getDataSource())) {
                                            nodeName = gkStationEvent.getDataSource() + "." + ((saveStationInfo.getCode() == null || saveStationInfo.getCode().equals("")) ? saveStationInfo.getCode() : (saveStationInfo.getCode() + ".")) + gkStationConfigurationVo.getVariableName();
                                        } else if (!StringUtils.isEmpty(saveStationInfo.getDataSource())) {
                                            nodeName = saveStationInfo.getDataSource() + "." + ((saveStationInfo.getCode() == null || saveStationInfo.getCode().equals("")) ? saveStationInfo.getCode() : (saveStationInfo.getCode() + ".")) + gkStationConfigurationVo.getVariableName();
                                        } else {
                                            nodeName = gkProductionLineVo.getCode() + "." + ((saveStationInfo.getCode() == null || saveStationInfo.getCode().equals("")) ? saveStationInfo.getCode() : (saveStationInfo.getCode() + ".")) + gkStationConfigurationVo.getVariableName();
                                        }
                                    }
                                }
                                if (nodeDTOV2.getDisplayName().equals(nodeName.trim())) {
                                    String value = OpcUATool.getValue(nodeDTOV2);
                                    for (int i = 0; i < 6; i++) {
                                        if (gkStationConfigurationVo.getVariableName().toLowerCase().equals("barcode" + (i == 0 ? "" : i)) && !StringUtils.isEmpty(value)) {
                                            values.add(value);
//                                            for (ConfigValueAndConfigConnectVo configValueAndConfigConnectVo : configValueAndConfigConnectVos) {
//                                                if (communication.equals("plc")) {
//                                                    if (value.equals(configValueAndConfigConnectVo.getValue())) {
//                                                        connectId = configValueAndConfigConnectVo.getStationConfigurationConnectId();
//                                                        connectIds.add(connectId);
//
//                                                    }
//                                                } else {
////                                                    log.info("gkstationconnect:{}", configValueAndConfigConnectVo);
//                                                    if (value.equals(configValueAndConfigConnectVo.getValue())) {
//                                                        connectId = configValueAndConfigConnectVo.getStationConfigurationConnectId();
//                                                        connectIds.add(connectId);
//                                                    }
//                                                }
//                                            }
                                        }
                                    }
                                    // 根据名称找到对应的最新值
                                    GkStationConfigurationValues stationConfigurationValues = new GkStationConfigurationValues();
                                    stationConfigurationValues.setStationConfigurationId(gkStationConfigurationVo.getId());
                                    stationConfigurationValues.setValue(value);
                                    stationConfigurationValues.setStationConfigurationConnectId(maxConnectId);
                                    stationConfigurationValues.setCreateAt(date);
                                    stationConfigurationValues.setLastModifyAt(date);
                                    gkStationConfigurationValuesList.add(stationConfigurationValues);
                                    // 判断生产是否合格
                                    if (gkStationConfigurationVo.getVariableName().equals("existence")) {
                                        // existence判定位0或者空时表示为正常生产工件不存在
                                        if (StringUtils.isEmpty(value) || value.equals("0") || value.equals("00") || value.equals("0.0")) {
                                            // 工件不存在
                                            flag = 0;
                                        }
                                        if (value.equals("3") || value.equals("03") || value.equals("3.0")) {
                                            // 标定模式
                                            flag = 3;
                                        }
                                        // existence只要是2或5那就判定为不合格
                                        if (value.equals("2") || value.equals("02") || value.equals("2.0")) {
                                            // 不合格零部件
                                            flag = 2;
                                        }
                                        if (value.equals("5") || value.equals("05") || value.equals("5.0")) {
                                            // 不合格零部件
                                            flag = 5;
                                        }
                                        if (value.equals("1") || value.equals("01") || value.equals("1.0")) {
                                            // 不合格零部件
                                            flag = 1;
                                        }
                                        if (value.equals("4") || value.equals("04") || value.equals("4.0")) {
                                            // 不合格零部件
                                            flag = 4;
                                        }
                                    }
                                    // 变量显示名称为总成条码的则是总成码
                                    if (gkStationConfigurationVo.getDisplayName().trim().equals("总成条码")) {
                                        assemblyCode = value;
                                    }
                                    // 变量显示名称为追溯条码的则是追溯条码
                                    if (gkStationConfigurationVo.getDisplayName().trim().equals("追溯条码")) {
                                        traceabilityCode = value;
                                    }
                                }
                                if (nodeDTOV2.getDisplayName().equals("DB_RECIPE.ProductType")) {
                                    productName = OpcUATool.getValue(nodeDTOV2);
                                }
                            }
                        }
                    }
                }
            } else {
                log.error(saveStationInfo.getName() + "未绑定通讯");
            }
        }
        if (CollUtil.isNotEmpty(values)) {
            connectIds = gkStationConfigurationValuesMapper.selectAllConnectIds(values);
            connectIds = connectIds.stream().distinct().collect(Collectors.toList());
        }
        // 匹配到值把添加的connect删除 并且改变需要保存值的connectId
        if (CollUtil.isNotEmpty(connectIds)) {
            List<GkStationConfigurationConnect> gkStationConfigurationConnects = gkStationConfigurationConnectMapper.selectInfoByIds(connectIds.toArray(new Long[0]));
            // 未完成的conn
            List<GkStationConfigurationConnect> noOkConn = new ArrayList<>();
            // 已完成的conn
            List<GkStationConfigurationConnect> isOkConn = new ArrayList<>();
            for (GkStationConfigurationConnect gkStationConfigurationConnect : gkStationConfigurationConnects) {
                if (gkStationConfigurationConnect.getIsOk() == null) {
                    noOkConn.add(gkStationConfigurationConnect);
                } else if (gkStationConfigurationConnect.getIsOk() == 0) {
                    noOkConn.add(gkStationConfigurationConnect);
                } else {
                    isOkConn.add(gkStationConfigurationConnect);
                }
            }
            // 有未完成的conn就进行合并  没有就进行复制
            if (CollUtil.isNotEmpty(noOkConn)) {
                connectId = noOkConn.get(noOkConn.size() - 1).getId();
                for (GkStationConfigurationConnect configurationConnect : noOkConn) {
                    if (configurationConnect.getId().longValue() > connectId.longValue()) {
                        connectId = configurationConnect.getId();
                    }
                }
                Long finalConnectId = connectId;
                connectIds = noOkConn.stream().map(GkStationConfigurationConnect::getId).filter(id -> id.longValue() != finalConnectId.longValue()).distinct().collect(Collectors.toList());
                // 合并前先删除已创建的conn
                gkStationConfigurationConnectMapper.deleteById(maxConnectId);

                if (CollUtil.isNotEmpty(connectIds)) {
                    List<GkStationConfigurationValues> gkStationConfigurationValues = gkStationConfigurationValuesMapper.selectByStationConfigurationConnectIds(connectIds);
                    List<GkStationConfigurationValues> gkStationConfigurationValuesList1 = new ArrayList<>();
                    for (GkStationConfigurationValues gkStationConfigurationValue : gkStationConfigurationValues) {
                        gkStationConfigurationValue.setStationConfigurationConnectId(connectId);
                        gkStationConfigurationValuesList1.add(gkStationConfigurationValue);
                    }
                    gkStationConfigurationValues = gkStationConfigurationValuesList1;
                    gkStationConfigurationValuesMapper.editListConnectId(gkStationConfigurationValues);
                    gkStationConfigurationConnectMapper.deleteByIds(connectIds);
                }
                for (GkStationConfigurationValues stationConfigurationValues : gkStationConfigurationValuesList) {
                    stationConfigurationValues.setStationConfigurationConnectId(connectId);
                }
                List<Long> configIds = gkStationConfigurationValuesList.stream().map(GkStationConfigurationValues::getStationConfigurationId).collect(Collectors.toList());
                int row = gkStationConfigurationValuesMapper.deleteByConfigIdsAndConnectId(configIds, connectId);
                maxConnectId = connectId;
            } else if (CollUtil.isNotEmpty(isOkConn)) {
                // 找到需要进行复制的保存信息，及返修模式
                connectId = isOkConn.get(isOkConn.size() - 1).getId();
                for (GkStationConfigurationConnect configurationConnect : isOkConn) {
                    if (configurationConnect.getId().longValue() > connectId.longValue()) {
                        connectId = configurationConnect.getId();
                    }
                }
                // 找到保存信息值，进行复制
                List<GkStationConfigurationValues> gkStationConfigurationValues = gkStationConfigurationValuesMapper.selectByStationConfigurationConnectId(connectId);
                List<GkStationConfigurationValues> gkStationConfigurationValuesList1 = new ArrayList<>();
                Date date1 = new Date();
                Map<Long, List<GkStationConfigurationValues>> collect = gkStationConfigurationValues.parallelStream().collect(Collectors.groupingBy(GkStationConfigurationValues::getStationConfigurationId));
                if (CollUtil.isNotEmpty(collect)){
                    for (Long aLong : collect.keySet()) {
                        List<GkStationConfigurationValues> gkStationConfigurationValuesList2 = collect.get(aLong);
                        if (CollUtil.isNotEmpty(gkStationConfigurationValuesList2)) {
                            GkStationConfigurationValues stationConfigurationValues = gkStationConfigurationValuesList2.stream().max(Comparator.comparing(GkStationConfigurationValues::getId)).get();
                            gkStationConfigurationValuesList1.add(stationConfigurationValues);
                            List<Long> deleteOldValueIds = gkStationConfigurationValuesList2.stream().filter(gkStationConfigurationValues1 -> gkStationConfigurationValues1.getId().longValue() != stationConfigurationValues.getId().longValue()).map(GkStationConfigurationValues::getId).collect(Collectors.toList());
                            if (CollUtil.isNotEmpty(deleteOldValueIds)) {
                                int row = gkStationConfigurationValuesMapper.deleteByIds(deleteOldValueIds);
                            }
                        }
                    }
                }
                gkStationConfigurationValues = gkStationConfigurationValuesList1;
                for (GkStationConfigurationValues gkStationConfigurationValue : gkStationConfigurationValues) {
                    gkStationConfigurationValue.setStationConfigurationConnectId(maxConnectId);
                    gkStationConfigurationValue.setCreateAt(date1);
                    gkStationConfigurationValue.setLastModifyAt(date1);
                }
                gkStationConfigurationValuesMapper.saveList(gkStationConfigurationValues);
                for (GkStationConfigurationValues stationConfigurationValues : gkStationConfigurationValuesList) {
                    stationConfigurationValues.setStationConfigurationConnectId(maxConnectId);
                }
                List<Long> configIds = gkStationConfigurationValuesList.stream().map(GkStationConfigurationValues::getStationConfigurationId).collect(Collectors.toList());
                int row = gkStationConfigurationValuesMapper.deleteByConfigIdsAndConnectId(configIds, maxConnectId);
            }
        }
        if (flag == 0) {
            // 不存在工件
            GkStationConfigurationConnect configurationConnect = new GkStationConfigurationConnect();
            configurationConnect.setId(maxConnectId);
            configurationConnect.setModels("");
            configurationConnect.setResult(-1);
            configurationConnect.setProductName(productName);
            configurationConnect.setLastModifyAt(new Date());
            if (StringUtils.isNotEmpty(assemblyCode)) {
                configurationConnect.setAssemblyCode(assemblyCode);
            }
            if (StringUtils.isNotEmpty(traceabilityCode)) {
                configurationConnect.setTraceabilityCode(traceabilityCode);
                configurationConnect.setIsOk(1);
            }
            gkStationConfigurationConnectMapper.edit(configurationConnect);
        } else if (flag == 3) {
            // 标定模式
            GkStationConfigurationConnect configurationConnect = new GkStationConfigurationConnect();
            configurationConnect.setId(maxConnectId);
            configurationConnect.setModels("标定模式");
            configurationConnect.setResult(-1);
            configurationConnect.setProductName(productName);
            configurationConnect.setLastModifyAt(new Date());
            if (StringUtils.isNotEmpty(assemblyCode)) {
                configurationConnect.setAssemblyCode(assemblyCode);
            }
            if (StringUtils.isNotEmpty(traceabilityCode)) {
                configurationConnect.setTraceabilityCode(traceabilityCode);
                configurationConnect.setIsOk(1);
            }
            gkStationConfigurationConnectMapper.edit(configurationConnect);
        } else
            // 不合格改变状态
            if (flag == 2 || flag == 5) {
                // 修改数据追溯状态
                GkStationConfigurationConnect configurationConnect = new GkStationConfigurationConnect();
                configurationConnect.setId(maxConnectId);
                configurationConnect.setResult(0);
                if (flag == 2) {
                    configurationConnect.setModels("正常生产");
                } else {
                    configurationConnect.setModels("返修模式");
                }
                configurationConnect.setProductName(productName);
                configurationConnect.setLastModifyAt(new Date());
                if (StringUtils.isNotEmpty(assemblyCode)) {
                    configurationConnect.setAssemblyCode(assemblyCode);
                }
                if (StringUtils.isNotEmpty(traceabilityCode)) {
                    configurationConnect.setTraceabilityCode(traceabilityCode);
                    configurationConnect.setIsOk(1);
                }
                gkStationConfigurationConnectMapper.edit(configurationConnect);

            } else if (flag == 1 || flag == 4) {
                // 工件正常生产合格和返修合格
                GkStationConfigurationConnect configurationConnect = new GkStationConfigurationConnect();
                configurationConnect.setId(maxConnectId);
                configurationConnect.setProductName(productName);
                if (flag == 1) {
                    configurationConnect.setModels("正常生产");
                } else {
                    configurationConnect.setModels("返修模式");
                }
                if (StringUtils.isNotEmpty(assemblyCode)) {
                    configurationConnect.setAssemblyCode(assemblyCode);
                }
                if (StringUtils.isNotEmpty(traceabilityCode)) {
                    configurationConnect.setTraceabilityCode(traceabilityCode);
                    configurationConnect.setIsOk(1);
                }
                configurationConnect.setResult(1);
                configurationConnect.setLastModifyAt(new Date());
                gkStationConfigurationConnectMapper.edit(configurationConnect);
            }
//        log.info("进入保存，保存内容为：{}", JSONUtil.toJsonStr(gkStationConfigurationValuesList));
        if (gkStationConfigurationValuesList.size()<0){
            gkStationConfigurationConnectMapper.deleteById(maxConnectId);
        }
        if (gkStationConfigurationValuesList.size() > 0) {
//            log.info("匹配保存的值：{}", JSONUtil.toJsonStr(gkStationConfigurationValuesList));
            List<Long> saveConfigIds = gkStationConfigurationValuesList.stream().map(GkStationConfigurationValues::getStationConfigurationId).collect(Collectors.toList());
            gkStationConfigurationValuesMapper.deleteByConfigIdsAndConnectId(saveConfigIds,maxConnectId);
            gkStationConfigurationValuesMapper.saveList(gkStationConfigurationValuesList);
        }
    }


    /**
     * 判断验证事件值是否与plc内的值匹配
     *
     * @param gkStationEventList         事件列表
     * @param gkStationAllList           所有事件的默认工位信息
     * @param gkSignalCommunications     所有通讯信息
     * @param gkStationConfigurationList 所有默认工位的变量信息
     * @return
     */
    private void judge(List<GkStationEvent> gkStationEventList,
                       List<GkStation> gkStationAllList, List<GkSignalCommunication> gkSignalCommunications,
                       List<GkStationConfiguration> gkStationConfigurationList, List<GkProductionLineVo> gkProductionLineVos) {

        for (GkStationEvent gkStationEvent : gkStationEventList) {
            List<NodeDTOV2> nodeDTOV2List = new ArrayList<>();
            OpcUaWriteReqV2 opcUaWriteReqV2 = new OpcUaWriteReqV2();
            for (GkStation gkStation : gkStationAllList) {
                if (gkStationEvent.getStationId().longValue() == gkStation.getId().longValue()) {
                    for (GkSignalCommunication gkSignalCommunication : gkSignalCommunications) {
                        if (gkStation.getSignalCommunicationId() == null) {
                            log.error("当前默认工位未配置通讯");
                            continue;
                        }
                        if (gkSignalCommunication.getId().longValue() == gkStation.getSignalCommunicationId().longValue()) {
                            nodeDTOV2List = map.get(gkSignalCommunication.getCommunicationProtocol());
                            opcUaWriteReqV2.setUid(gkSignalCommunication.getCommunicationProtocol());
                        }
                    }
                }
            }
            if (nodeDTOV2List == null) {
//                log.info("连接数据为空");
                continue;
            }
            // 条件变量id和信息
            Long conditionConfigurationId = gkStationEvent.getConditionConfigurationId();
            GkStationConfiguration conditionConfigurationInfo = new GkStationConfiguration();
            // 需要改变变量id和信息
            Long configurationId = gkStationEvent.getConfigurationId();
            GkStationConfiguration configurationInfo = new GkStationConfiguration();
            // 根据id找到事件条件变量信息和修改变量信息
            for (GkStationConfiguration gkStationConfiguration : gkStationConfigurationList) {
                if (gkStationConfiguration.getId().longValue() == conditionConfigurationId.longValue()) {
                    conditionConfigurationInfo = gkStationConfiguration;
                }
                if (gkStationConfiguration.getId().longValue() == configurationId.longValue()) {
                    configurationInfo = gkStationConfiguration;
                }
            }
            // 获取事件条件变量值
            String conditionValue = gkStationEvent.getConditionValue();
            // 根据值判断事件是否触发
            for (NodeDTOV2 nodeDTOV2 : nodeDTOV2List) {
                String nodeDTOV2value = OpcUATool.getValue(nodeDTOV2);
                // 数据源拼接变量名称进行路径匹配
                if (nodeDTOV2.getDisplayName().equals("data_pc_plc.plc_request." + conditionConfigurationInfo.getVariableName())) {
                    if (conditionValue.equals(nodeDTOV2value)) {
                        GkStationConfiguration finalConfigurationInfo = configurationInfo;
                        if (nodeDTOV2value.equals("16")) {
                            if (saveConfigureMap.get(finalConfigurationInfo.getId()) == null) {
                                saveConfigureMap.put(finalConfigurationInfo.getId(), true);
                                new Thread(new Runnable() {
                                    @Override
                                    public void run() {
                                        log.info("保存{}工位数据", gkStationEvent.getConditionStationId());
                                        ArrayList<NodeDTOV2> writeNodeList = new ArrayList<>();
                                        NodeDTOV2 nodeDTOV21 = new NodeDTOV2();
                                        nodeDTOV21.setNodeValue(0);
                                        nodeDTOV21.setNodeName(nodeDTOV2.getDisplayName());
                                        nodeDTOV21.setNodeType(nodeDTOV2.getNodeType().toUpperCase());
                                        writeNodeList.add(nodeDTOV21);
                                        NodeDTOV2 nodeDTOV22 = new NodeDTOV2();
                                        // 把需要改的变量的值转换为object
                                        finalConfigurationInfo.setDefaultValue(gkStationEvent.getValue());
                                        Object configurationValue = getConfigurationValue(finalConfigurationInfo);
                                        nodeDTOV22.setNodeValue(configurationValue);
                                        // 拼接需要改变变量的名称
                                        nodeDTOV22.setNodeName("data_pc_plc.pc_reply." + finalConfigurationInfo.getVariableName());
                                        if (finalConfigurationInfo.getDataType().equals("boolean")) {
                                            finalConfigurationInfo.setDataType("BOOL");
                                        } else {
                                            finalConfigurationInfo.setDataType(finalConfigurationInfo.getDataType().toUpperCase());
                                        }
                                        nodeDTOV22.setNodeType(finalConfigurationInfo.getDataType().toUpperCase());
                                        writeNodeList.add(nodeDTOV22);
                                        opcUaWriteReqV2.setWriteNodeList(writeNodeList);
                                        // 发送修改命令
                                        if (communication.equals("socket")) {
                                            writerToObj(opcUaWriteReqV2);
                                            String[] split = gkStationEvent.getConditionStationId().split(",");
                                            // 需要读取的工位id
                                            List<Long> saveOrScanningStationIds = new ArrayList<>();
                                            for (String s : split) {
                                                saveOrScanningStationIds.add(Long.parseLong(s));
                                            }
                                            // 保存需要读取的工位变量信息
                                            saveConfigurationValue(gkProductionLineVos, gkStationEvent, saveOrScanningStationIds, gkSignalCommunications);
                                        } else {
                                            Ret<List<NodeDTOV2>> listRet = opcUaServiceV2.writeData(opcUaWriteReqV2);
//                                            log.info("下发参数：{}", JSONUtil.toJsonStr(opcUaWriteReqV2));
                                            if (listRet != null) {
                                                List<NodeDTOV2> data = listRet.getData();
//                                                log.info("返回验证：{}", JSONUtil.toJsonStr(data));
                                                int flag = 0;
                                                if (CollUtil.isNotEmpty(data)) {
                                                    for (NodeDTOV2 datum : data) {
                                                        if (datum.getStatusCode().longValue() != 0) {
                                                            log.info("修改失败：{}", JSONUtil.toJsonStr(opcUaWriteReqV2));
                                                            saveConfigureMap.put(finalConfigurationInfo.getId(), false);
                                                            flag = 1;
                                                        }
                                                    }
                                                }
                                                if (flag == 0) {
//                                                    log.info("修改成功后的锁值：{}", saveConfigureMap.get(finalConfigurationInfo.getId()));
                                                    String[] split = gkStationEvent.getConditionStationId().split(",");
                                                    // 需要读取的工位id
                                                    List<Long> saveOrScanningStationIds = new ArrayList<>();
                                                    for (String s : split) {
                                                        saveOrScanningStationIds.add(Long.parseLong(s));
                                                    }
                                                    // 保存需要读取的工位变量信息
                                                    saveConfigurationValue(gkProductionLineVos, gkStationEvent, saveOrScanningStationIds, gkSignalCommunications);
                                                }
                                            } else {
                                                saveConfigureMap.put(finalConfigurationInfo.getId(), false);
                                            }
                                        }
                                    }
                                }).start();
                            } else if (!saveConfigureMap.get(finalConfigurationInfo.getId())) {
                                saveConfigureMap.put(finalConfigurationInfo.getId(), true);
                                // 多个工位同时请求保存使用多线程
                                new Thread(new Runnable() {
                                    @Override
                                    public void run() {
                                        log.info("保存{}工位数据", gkStationEvent.getConditionStationId());
                                        ArrayList<NodeDTOV2> writeNodeList = new ArrayList<>();
                                        NodeDTOV2 nodeDTOV21 = new NodeDTOV2();
                                        nodeDTOV21.setNodeValue(0);
                                        nodeDTOV21.setNodeName(nodeDTOV2.getDisplayName());
                                        nodeDTOV21.setNodeType(nodeDTOV2.getNodeType().toUpperCase());
                                        writeNodeList.add(nodeDTOV21);
                                        NodeDTOV2 nodeDTOV22 = new NodeDTOV2();
                                        // 把需要改的变量的值转换为object
                                        finalConfigurationInfo.setDefaultValue(gkStationEvent.getValue());
                                        Object configurationValue = getConfigurationValue(finalConfigurationInfo);
                                        nodeDTOV22.setNodeValue(configurationValue);
                                        // 拼接需要改变变量的名称
                                        nodeDTOV22.setNodeName("data_pc_plc.pc_reply." + finalConfigurationInfo.getVariableName());
                                        if (finalConfigurationInfo.getDataType().equals("boolean")) {
                                            finalConfigurationInfo.setDataType("BOOL");
                                        } else {
                                            finalConfigurationInfo.setDataType(finalConfigurationInfo.getDataType().toUpperCase());
                                        }
                                        nodeDTOV22.setNodeType(finalConfigurationInfo.getDataType().toUpperCase());
                                        writeNodeList.add(nodeDTOV22);
                                        opcUaWriteReqV2.setWriteNodeList(writeNodeList);
                                        // 发送修改命令
                                        if (communication.equals("socket")) {
                                            writerToObj(opcUaWriteReqV2);
                                            String[] split = gkStationEvent.getConditionStationId().split(",");
                                            // 需要读取的工位id
                                            List<Long> saveOrScanningStationIds = new ArrayList<>();
                                            for (String s : split) {
                                                saveOrScanningStationIds.add(Long.parseLong(s));
                                            }
                                            // 保存需要保存的工位变量信息
                                            saveConfigurationValue(gkProductionLineVos, gkStationEvent, saveOrScanningStationIds, gkSignalCommunications);
                                        } else {
                                            Ret<List<NodeDTOV2>> listRet = opcUaServiceV2.writeData(opcUaWriteReqV2);
//                                            log.info("下发参数：{}", JSONUtil.toJsonStr(opcUaWriteReqV2));
                                            if (listRet != null) {
                                                List<NodeDTOV2> data = listRet.getData();
//                                                log.info("返回验证：{}", JSONUtil.toJsonStr(data));
                                                int flag = 0;
                                                if (CollUtil.isNotEmpty(data)) {
                                                    for (NodeDTOV2 datum : data) {
                                                        if (datum.getStatusCode().longValue() != 0) {
                                                            log.info("修改失败：{}", JSONUtil.toJsonStr(opcUaWriteReqV2));
                                                            saveConfigureMap.put(finalConfigurationInfo.getId(), false);
                                                            flag = 1;
                                                        }
                                                    }
                                                }
                                                if (flag == 0) {
//                                                    log.info("修改成功后的锁值：{}", saveConfigureMap.get(finalConfigurationInfo.getId()));
                                                    String[] split = gkStationEvent.getConditionStationId().split(",");
                                                    // 需要读取的工位id
                                                    List<Long> saveOrScanningStationIds = new ArrayList<>();
                                                    for (String s : split) {
                                                        saveOrScanningStationIds.add(Long.parseLong(s));
                                                    }
                                                    // 保存需要保存的工位变量信息
                                                    saveConfigurationValue(gkProductionLineVos, gkStationEvent, saveOrScanningStationIds, gkSignalCommunications);
                                                }
                                            } else {
                                                saveConfigureMap.put(finalConfigurationInfo.getId(), false);
                                            }
                                        }
                                    }
                                }).start();
                            }
                        }
                        if (nodeDTOV2value.equals("32")) {
                            // 需要调用扫码功能
                            Long conditionId = null;
                            try {
                                conditionId = Long.parseLong(gkStationEvent.getConditionStationId());
                            } catch (NumberFormatException e) {
                                conditionId = null;
                            }
                            if (scanningMap.get(conditionId) == null) {
                                // 设置工位锁相同工位同时只允许一个扫码
                                scanningMap.put(conditionId, true);
                                // 调用扫码功能
                                Scancodematching(conditionId, gkSignalCommunications, gkProductionLineVos, gkStationEvent);
                            } else if (!scanningMap.get(conditionId)) {
                                scanningMap.put(conditionId, true);
                                Scancodematching(conditionId, gkSignalCommunications, gkProductionLineVos, gkStationEvent);
                            }
                        }
                    } else {
                        if (saveConfigureMap.get(configurationInfo.getId()) != null && conditionValue.equals("16")) {
                            if (saveConfigureMap.get(configurationInfo.getId())) {
                                saveConfigureMap.put(configurationInfo.getId(), false);
                            }
                        }
                    }
                }
            }
        }
    }

    public void writerToObj(OpcUaWriteReqV2 opcUaWriteReqV2) {
        List<NodeDTOV2> writeNodeList = opcUaWriteReqV2.getWriteNodeList();
        ArrayList<ServiceData> nodeList = new ArrayList<>();
        for (NodeDTOV2 nodeDTOV2 : writeNodeList) {
            ServiceData serviceData = new ServiceData();
            serviceData.setDisplayName(nodeDTOV2.getNodeName());
            serviceData.setNodeName(nodeDTOV2.getNodeName());
            serviceData.setNodeValue(nodeDTOV2.getNodeValue());
            serviceData.setNodeType(nodeDTOV2.getNodeType());
            nodeList.add(serviceData);
        }
        SocketDataVo socketDataVo = new SocketDataVo();
        socketDataVo.setUid(opcUaWriteReqV2.getUid());
        socketDataVo.setNodeList(nodeList);
        try {
            writer.write("setData?" + JSON.toJSONString(socketDataVo) + "\n");
            writer.flush();
            reader.readLine();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 把变量内的值转为对象   String->Object
     * @param gkStationConfiguration 变量信息
     * @return 对象
     */
    public Object getConfigurationValue(GkStationConfiguration gkStationConfiguration) {
        Object obj = null;
        if (gkStationConfiguration.getDataType().equals("BOOL")) {
            if (StringUtils.equals(gkStationConfiguration.getDefaultValue(), "true")) {
                obj = Boolean.TRUE;
            } else {
                obj = Boolean.FALSE;
            }
        } else if (gkStationConfiguration.getDataType().equals("STRING")) {
            if (com.sgl.common.utils.StringUtils.isEmpty(gkStationConfiguration.getDefaultValue())) {
                obj = "";
            } else {
                obj = gkStationConfiguration.getDefaultValue();
            }
        } else if (StringUtils.isEmpty(gkStationConfiguration.getDefaultValue())) {
            obj = 0;
        } else {
            Pattern pattern = Pattern.compile("[0-9]*\\.?[0-9]+");
            Matcher isNum = pattern.matcher(gkStationConfiguration.getDefaultValue());
            if (!isNum.matches()) {
                obj = null;
            } else {
                if (gkStationConfiguration.getDefaultValue().indexOf('.') > 0) {
                    obj = Float.parseFloat(gkStationConfiguration.getDefaultValue());
                } else {
                    obj = Integer.parseInt(gkStationConfiguration.getDefaultValue());
                }
            }
        }
        return obj;
    }


    /**
     * 数据统计数据采集
     */
    @PostConstruct
    public void dataStatisticsTask() {
        // todo 2023.2.17版直接线程错误结束
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    List<GkStatistics> gkStatistics = gkStatisticsMapper.toDayInfo();
                    List<GkSignalCommunication> gkSignalCommunications = gkSignalCommunicationMapper.list(null);
                    List<GkSetting> list = gkSettingMapper.list();
                    if (!CollUtil.isNotEmpty(gkStatistics)) {
                        for (GkSignalCommunication gkSignalCommunication : gkSignalCommunications) {
                            GkStatistics gkStatistic = new GkStatistics();
                            gkStatistic.setGkSignalId(gkSignalCommunication.getId());
                            gkStatistic.setProductRealNum(0);
                            gkStatistic.setProductNum(0);
                            gkStatistic.setPlanProductNum(list.get(0).getPlanProductNum());
                            gkStatistic.setProductNgNum(0);
                            gkStatistic.setPlanBit(list.get(0).getPlanBit());
                            gkStatistic.setRealBit(0f);
                            gkStatistic.setRuntime(0);
                            gkStatistic.setCreateAt(new Date());
                            gkStatistic.setLastModifyAt(new Date());
                            gkStatisticsMapper.insert(gkStatistic);
                        }
                    } else {
                        if (CollUtil.isNotEmpty(map)) {
                            for (String s : map.keySet()) {
                                List<NodeDTOV2> nodeDTOV2List = map.get(s);
                                Long gkSignalId = null;
                                for (GkSignalCommunication gkSignalCommunication : gkSignalCommunications) {
                                    if (s.equals(gkSignalCommunication.getCommunicationProtocol())) {
                                        gkSignalId = gkSignalCommunication.getId();
                                    }
                                }
                                GkStatistics gkStatistic = null;
                                for (GkStatistics statistic : gkStatistics) {
                                    if (statistic.getGkSignalId().longValue() == gkSignalId.longValue()) {
                                        gkStatistic = statistic;
                                    }
                                }
                                if (gkSignalId.longValue() == 24) {
                                    if (CollUtil.isNotEmpty(nodeDTOV2List)) {
                                        for (int i = 1; i <= 16; i++) {
                                            if (i == 12) {
                                                for (NodeDTOV2 nodeDTOV2 : nodeDTOV2List) {
                                                    Object nodeValue = nodeDTOV2.getNodeValue();
                                                    if (nodeValue != null) {
                                                        GkStatistics gkStatistics1 = new GkStatistics();
                                                        gkStatistics1.setId(gkStatistic.getId());
                                                        if (nodeDTOV2.getDisplayName().equals("St1.OKCount[12]")) {
                                                            gkStatistics1.setProductNum(Integer.parseInt(nodeValue.toString()));
                                                            if (gkStatistic.getProductNgNum() != null) {
                                                                gkStatistics1.setProductRealNum(gkStatistics1.getProductNum() + gkStatistic.getProductNgNum());
                                                            } else {
                                                                gkStatistics1.setProductRealNum(gkStatistics1.getProductNum());
                                                            }
                                                        }
                                                        if (nodeDTOV2.getDisplayName().equals("St1.NGCount[12]")) {
                                                            gkStatistics1.setProductNgNum(Integer.parseInt(nodeValue.toString()));
                                                            if (gkStatistic.getProductNum() != null) {
                                                                gkStatistics1.setProductRealNum(gkStatistics1.getProductNgNum() + gkStatistic.getProductNum());
                                                            } else {
                                                                gkStatistics1.setProductRealNum(gkStatistics1.getProductNgNum());
                                                            }
                                                        }
                                                        if (nodeDTOV2.getDisplayName().equals("St1.CycleTime[12]")) {
                                                            gkStatistics1.setRealBit(Float.parseFloat(nodeValue.toString()));
                                                        }
                                                        if (nodeDTOV2.getDisplayName().equals("St1.RunTime")) {
                                                            gkStatistics1.setRuntime(Integer.parseInt(nodeValue.toString()));
                                                            GkReservedInfo gkReservedInfo = new GkReservedInfo();
                                                            Integer i1 = Integer.parseInt(nodeValue.toString()) / 60;
                                                            gkReservedInfo.setId(6l);
                                                            gkReservedInfo.setValue(i1.toString() + "分钟");
                                                            gkReservedInfoMapper.edit(gkReservedInfo);
                                                        }
                                                        if (gkStatistics1.getProductNgNum() == null && gkStatistics1.getProductNum() == null && gkStatistics1.getProductRealNum() == null && gkStatistics1.getRealBit() == null && gkStatistics1.getRuntime() == null) {
                                                            continue;
                                                        }
                                                        gkStatisticsMapper.updateInfo(gkStatistics1);
                                                    }
                                                }
                                                continue;
                                            }
                                            String nodeName = "St1.OKCount[" + i + "]";
                                            String nodeName1 = "St1.NGCount[" + i + "]";
                                            String nodeName2 = "St1.CycleTime[" + i + "]";
                                            GkShowStationInfo gkShowStationInfo = new GkShowStationInfo();
                                            for (NodeDTOV2 nodeDTOV2 : nodeDTOV2List) {
                                                Object nodeValue = nodeDTOV2.getNodeValue();
                                                if (nodeValue != null) {
                                                    Long id = new Long(i);
                                                    if (i > 12) {
                                                        id = new Long(i - 1);
                                                    }
                                                    gkShowStationInfo.setId(id);
                                                    if (nodeDTOV2.getDisplayName().equals(nodeName)) {
                                                        // 工位OK数
                                                        gkShowStationInfo.setOkCount(Integer.parseInt(nodeValue.toString()));
                                                    }
                                                    if (nodeDTOV2.getDisplayName().equals(nodeName1)) {
                                                        // 工位NG数
                                                        gkShowStationInfo.setNgCount(Integer.parseInt(nodeValue.toString()));
                                                    }
                                                    if (nodeDTOV2.getDisplayName().equals(nodeName2)) {
                                                        // 工位节拍
                                                        gkShowStationInfo.setCycleTime(Integer.parseInt(nodeValue.toString()));
                                                    }
                                                    if (nodeDTOV2.getDisplayName().equals("DB_RECIPE.NG_CNT")) {
                                                        String value = OpcUATool.getValue(nodeDTOV2);
                                                        GkReservedInfo gkReservedInfo = new GkReservedInfo();
                                                        gkReservedInfo.setValue(value);
                                                        gkReservedInfo.setId(7l);
                                                        gkReservedInfoMapper.edit(gkReservedInfo);
                                                    }
                                                }
                                            }
                                            if (gkShowStationInfo.getNgCount() == null && gkShowStationInfo.getOkCount() == null && gkShowStationInfo.getCycleTime() == null) {
                                                continue;
                                            }
                                            gkShowStationInfoMapper.edit(gkShowStationInfo);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }).start();
    }
}


